#!/usr/bin/python3.6
# -*- coding: utf-8 -*-
# @Time    : 2024/11/26 12:35
# @Author  : zmz
# @File    : internal_rate_of_return.py
# @function: 内部收益率、方案比选
# @Software: PyCharm

import PySimpleGUI as sg
import numpy as np
import numpy_financial as npf

import debug_infomation as _debug
import public_data as _pub

# 内部收益率布局
irr_layout = [
    [sg.Text('方案一 现金流数据(以英文逗号隔开输入)：')],
    [sg.InputText(key='irr1', default_text="-1000, 100, 200, 300, 400, 500", size=(130, 1))],
    [sg.Text('方案二 现金流数据(以英文逗号隔开输入)：')],
    [sg.InputText(key='irr2', default_text="-1000, 100, 200, 300, 400, 500", size=(130, 1))],
    [sg.Text('方案三 现金流数据(以英文逗号隔开输入)：')],
    [sg.InputText(key='irr3', default_text="-1000, 100, 200, 300, 400, 500", size=(130, 1))],
    [sg.Text('方案四 现金流数据(以英文逗号隔开输入)：')],
    [sg.InputText(key='irr4', default_text="-1000, 100, 200, 300, 400, 500", size=(130, 1))],
    [sg.Button('计算 IRR')]
]

# 方案比选布局
com_layout = [
    [sg.Text('方案一 投资总额：'), sg.Text(' 各期现金流数据(以英文逗号隔开输入)：')],
    [sg.InputText(key='tz1', default_text="124200", size=(15, 1)),
     sg.InputText(key='cf1', default_text="-25000,2000,2000,2000,2000, 2000,2000,2000,67000", size=(130, 1))],
    [sg.Text('方案二 投资总额：'), sg.Text(' 各期现金流数据(以英文逗号隔开输入)：')],
    [sg.InputText(key='tz2', default_text="124200", size=(15, 1)),
     sg.InputText(key='cf2', default_text="-25000,2000,2000,2000,2000, 2000,2000,2000,67000", size=(130, 1))],
    [sg.Text('方案三 投资总额：'), sg.Text(' 各期现金流数据(以英文逗号隔开输入)：')],
    [sg.InputText(key='tz3', default_text="32600", size=(15, 1)),
     sg.InputText(key='cf3', default_text="-25000,2000,2000,2000,2000, 2000,2000,2000,67000", size=(130, 1))],
    [sg.Text('方案四 投资总额：'), sg.Text(' 各期现金流数据(以英文逗号隔开输入)：')],
    [sg.InputText(key='tz4', default_text="32600", size=(15, 1)),
     sg.InputText(key='cf4', default_text="-25000,2000,2000,2000,2000, 2000,2000,2000,67000", size=(130, 1))],
    [sg.Text('折现率r（以小数形式，如0.05表示5%）：'), sg.Text('MARR（以小数形式，如0.07表示7%）：')],
    [sg.InputText(key='R_INPUT', default_text="0.06", size=(15, 1)),
     sg.InputText(key='marr', default_text="0.09", size=(15, 1))],
    [sg.Text(' 多期投资总额按折现率r进行期初现值计算. 折现率r（以小数形式，如0.05表示5%）')],
    [sg.Button('进行比选')]
]


# 标准接口实现. 每个计算都需要包含.
def update_pub_data(pub_data):
    if not pub_data:
        com_layout[9][0].update(_pub.pub_r)
        com_layout[9][1].update(_pub.pub_marr)
        return
    com_layout[9][0].update(pub_data['PUB_R_INPUT-'])
    com_layout[9][1].update(pub_data['PUB_MARR_INPUT-'])


global_order = []


# 标准接口实现. 每个计算都需要包含.
def update_excel_data(excel_data):
    grouped_data = excel_data.groupby('solution')

    # 定义特定顺序
    # order = ['X1Z', 'X1D']
    # 获取分组顺序（按首次出现顺序）
    global global_order
    global_order = excel_data['solution'].drop_duplicates().tolist();
    # order = ['Q1Z', 'Q1D', 'Q2Z', 'Q2D']
    # order = ['Y1Z', 'Y1D', 'Y2Z', 'Y2D']
    # 按特定顺序重新索引分组结果
    grouped_data_ordered = {key: grouped_data.get_group(key) for key in global_order if key in grouped_data.groups}

    index = 1
    for group_name, grouped_data in grouped_data_ordered.items():
        # 获取 net_cash_flow 列的数据
        print(group_name)
        net_cash_flow = grouped_data['et_cash_flow']

        # 将 net_cash_flow 列的数据转换为逗号分隔的字符串
        cash_flow_str = ', '.join(map(str, net_cash_flow))

        # 更新 irr_layout 中的现金流
        irr_layout[index][0].update(value=cash_flow_str)
        # 更新 com_layout 中的现金流
        com_layout[index][1].update(value=cash_flow_str)

        total_investment = round(npf.npv(_pub.pub_r, grouped_data['total_investment']), 2)
        com_layout[index][0].update(value=total_investment)

        index += 2;
        # 传递 net_cash_flow 列的数据给 _irr.Internal_Rate_of_Return_Handle 函数
        # _irr.Internal_Rate_of_Return_Handle(net_cash_flow)

        # i = float(values['marr'])
        # npf.pv(i, n, a, f)


# 内部收益率计算处理
def Internal_Rate_of_Return_Handle(values):
    # 获取输入的现金流数据并转换为列表
    keys = ['irr1', 'irr2', 'irr3', 'irr4']
    for key in keys:
        cash_flow_str = values[key]
        try:
            cash_flows = [float(x.strip()) for x in cash_flow_str.split(',')]
            # 计算 IRR
            _irr = npf.irr(cash_flows)
            temp_value = "{:.3%}".format(_irr)
            _debug.info(f'内部收益率 (IRR) for {key}：{temp_value}')
        except ValueError:
            sg.popup_error('请输入有效的数字，且用逗号正确隔开！')
        except Exception as e:
            sg.popup_error(f'计算 IRR 时出错：{e}')


# 方案比选处理
def sheme_comparison_handle(values):
    # 获取方案一的现金流数据并转换为列表
    cf1_str = values['cf1']
    try:
        cf1 = [float(x.strip()) for x in cf1_str.split(',')]
    except ValueError:
        sg.popup_error('请输入方案一有效的数字，且用逗号正确隔开！')
        return False
    # 获取方案二的现金流数据并转换为列表
    cf2_str = values['cf2']
    try:
        cf2 = [float(x.strip()) for x in cf2_str.split(',')]
    except ValueError:
        sg.popup_error('请输入方案二有效的数字，且用逗号正确隔开！')
        return False

        # 获取方案二的现金流数据并转换为列表
    cf3_str = values['cf3']
    try:
        cf3 = [float(x.strip()) for x in cf3_str.split(',')]
    except ValueError:
        sg.popup_error('请输入方案三有效的数字，且用逗号正确隔开！')
        return False

        # 获取方案二的现金流数据并转换为列表
    cf4_str = values['cf4']
    try:
        cf4 = [float(x.strip()) for x in cf4_str.split(',')]
    except ValueError:
        sg.popup_error('请输入方案三有效的数字，且用逗号正确隔开！')
        return False

    # 获取基准MARR
    marr = float(values['marr'])

    # 构造无为方案数组.
    cf1_length = len(cf1)

    # 生成一个全是 0 的数组，长度与 cf1 相同
    zero_array = [0.0] * cf1_length
    _debug.info('marr:{},对应的无为方案为DN.'.format(marr))
    # 确定投资较大和较小的方案
    # 按投资金额进行排序,添加无为方案
    investments_with_labels = []
    if global_order[0].startswith('X'):
        investments_with_labels = [
            (0, 'tz0', zero_array),
            (float(values['tz1']), global_order[0], cf1),
            (float(values['tz2']), global_order[1], cf2),

        ]
    else:
        investments_with_labels = [
            (0, 'tz0', zero_array),
            (float(values['tz1']), global_order[0], cf1),
            (float(values['tz2']), global_order[1], cf2),
            (float(values['tz3']), global_order[2], cf3),
            (float(values['tz4']), global_order[3], cf4)

            # (float(values['tz1']), 'X1Z', cf1),
            # (float(values['tz2']), 'X1D', cf2),
            # (float(values['tz3']), 'Y2Z', cf3),
            # (float(values['tz4']), 'Y2D', cf4)

            # (float(values['tz1']), 'X1Z', cf1),
            # (float(values['tz2']), 'X1D', cf2),
        ]
    # 根据第一个值升序排序
    sorted_investments = sorted(investments_with_labels, key=lambda x: x[0])

    # better project,默认未无为方案.
    bp = sorted_investments[0]
    loopcnts = len(sorted_investments)
    for i in range(loopcnts - 1):
        # print(bp[2])
        # print(sorted_investments[i+1])
        increment_cf = [a - b for a, b in zip(bp[2], sorted_investments[i + 1][2])]
        _debug.info(
            '方案{}与方案{}进行增量比选。'.format(
                bp[1], sorted_investments[i + 1][1]))
        cp_val = sheme_comparison_caculate(increment_cf, marr, sorted_investments[i + 1][1])
        bp = sorted_investments[i + 1] if cp_val else bp
        if i + 1 > loopcnts:
            break;

    print(bp)

    # # 按投资金额排序
    #
    # investment1 = sorted_investments_with_labels[0][0]
    # investment2 = sorted_investments_with_labels[1][0]
    # investment3 = sorted_investments_with_labels[2][0]
    #
    # increment_cf = investment1
    # #投资最少与无为方案比较.
    # cp_val = sheme_comparison_caculate(increment_cf, marr, sorted_investments_with_labels[0][1])
    # if cp_val :
    #     increment_cf = [a - b for a, b in zip(investment1, investment2)]
    #     # 投资次大比较.
    #     cp_val = sheme_comparison_caculate(increment_cf, marr, sorted_investments_with_labels[1][1])
    #     if cp_val :
    #         #投资最大与次大比较
    #         increment_cf = [a - b for a, b in zip(investment2, investment3)]
    #         cp_val = sheme_comparison_caculate(increment_cf, marr, sorted_investments_with_labels[2][1])
    # else :
    #     # 投资次少与无为方案.
    #     increment_cf = investment2
    #     cp_val = sheme_comparison_caculate(increment_cf, marr, sorted_investments_with_labels[0][1])
    #
    #
    #
    # if investment1 > investment2:
    #     increment_cf = [a - b for a, b in zip(cf1, cf2)]
    #     larger_investment_scheme = "方案一"
    # else:
    #     increment_cf = [a - b for a, b in zip(cf2, cf1)]
    #     larger_investment_scheme = "方案二"
    #
    # # 计算增量现金流的IRR，并比选
    # return sheme_comparison_caculate(increment_cf, marr, larger_investment_scheme)


# 方案比选处理
def sheme_comparison_caculate(increment_cf, marr, larger_investment_scheme):
    # 计算增量现金流的IRR，并比选
    try:
        increment_irr = npf.irr(increment_cf)
        if np.isnan(increment_irr):
            _debug.info('增量投资的内部收益率（IRR）{:.2%}计算错误,请检查数据。'.format(
                increment_irr))
            return False
        if increment_irr > marr:
            _debug.info('比选结果：增量投资的内部收益率（IRR）{:.2%}大于基准MARR {:.2%}，投资较大的{}方案更优。'.format(
                increment_irr, marr, larger_investment_scheme))
            return True
        # sg.popup('比选结果：增量投资的内部收益率（IRR）{:.2%}大于基准MARR {:.2%}，{}是投资大的方案且更优。'.format(increment_irr, marr, larger_investment_scheme))
        elif increment_irr < marr:
            _debug.info('比选结果：增量投资的内部收益率（IRR）{:.2%}小于基准MARR {:.2%}，投资较大的方案（{}）不是更优。'.format(
                increment_irr, marr, larger_investment_scheme))
            return False
        else:
            _debug.info(
                '比选结果：增量投资的内部收益率（IRR）{:.2%}等于基准MARR {:.2%}，可根据其他因素进一步抉择，投资大的方案是{}。'.format(
                    increment_irr, marr, larger_investment_scheme))
            return False
    except Exception as e:
        sg.popup_error(f'计算增量现金流IRR时出错：{e}')
    return True
